﻿using BoldBrick.Web.Parameters;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.ComponentModel.DataAnnotations;
using System.Web;
using System.Collections.Specialized;

namespace BoldBrick.Web.UnitTests
{
    
    
    /// <summary>
    ///This is a test class for RequestQueryParametersProviderTest and is intended
    ///to contain all RequestQueryParametersProviderTest Unit Tests
    ///</summary>
    [TestClass()]
    public class RequestQueryParametersProviderTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        public class TestQueryParameters
        {
            [Required]
            [ParameterName("guid_param")]
            public Guid GuidParamRequired { get; set; }

            [ParameterName("int_param")]
            public int? IntParamNullable { get; set; }
            
            [ParameterName("string_param")]
            public string StringParam { get; set; }
            
            [Required]
            [ParameterName("bool_param")]
            public bool BoolParamRequired { get; set; }

            [DisplayFormat(DataFormatString = "dd-MM-yyyy")]
            [ParameterName("datetime_param")]
            public DateTime DateTimeParam { get; set; }

            [DisplayFormat(DataFormatString = "dd-MM-yyyy H:mm")]
            [ParameterName("datetime_param2")]
            public DateTime DateTimeParam2 { get; set; }

            [ParameterName("int_array_param")]
            public int[] IntArrayParamNullable { get; set; }
        }

        #region LoadParameters Tests
        [TestMethod()]
        public void LoadParametersTest_Guid()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            Guid testGuid = Guid.NewGuid();

            string query = "?guid_param=" + testGuid.ToString() + "&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);

            Assert.IsNotNull(actual);
            Assert.AreEqual(testGuid, actual.GuidParamRequired);
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidParameterException))]
        public void LoadParametersTest_Guid_Required()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            Guid testGuid = Guid.NewGuid();

            string query = "?bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);
        }

        [TestMethod()]
        [ExpectedException(typeof(InvalidParameterException))]
        public void LoadParametersTest_Guid_Incorrect()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            string query = "?guid_param=xxx&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);
        }

        [TestMethod()]
        public void LoadParametersTest_Date()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            DateTime testDate = DateTime.Today;
            Guid testGuid = Guid.NewGuid();

            string query = "?guid_param=" + testGuid.ToString() + "&datetime_param=" + testDate.ToString("dd-MM-yyyy") + "&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);

            Assert.IsNotNull(actual);
            Assert.AreEqual(testDate, actual.DateTimeParam);
        }

        [ExpectedException(typeof(InvalidParameterException))]
        [TestMethod()]
        public void LoadParametersTest_Date_Invalid()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            DateTime testDate = DateTime.Today;
            Guid testGuid = Guid.NewGuid();

            string query = "?guid_param=" + testGuid.ToString() + "&datetime_param=" + testDate.ToString("yyyy") + "&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);
        }

        [TestMethod()]
        public void LoadParametersTest_DateTime()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            DateTime testDate = DateTime.Today;
            Guid testGuid = Guid.NewGuid();

            string query = "?guid_param=" + testGuid.ToString() + "&datetime_param2=" + testDate.ToString("dd-MM-yyyy H:mm") + "&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);

            Assert.IsNotNull(actual);
            Assert.AreEqual(testDate, actual.DateTimeParam2);
        }

        [ExpectedException(typeof(InvalidParameterException))]
        [TestMethod()]
        public void LoadParametersTest_DateTime_Invalid()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            DateTime testDate = DateTime.Today;
            Guid testGuid = Guid.NewGuid();

            string query = "?guid_param=" + testGuid.ToString() + "&datetime_param2=" + testDate.ToString("yyyy H:mm") + "&bool_param=true";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);
        }

        [TestMethod()]
        public void LoadParametersTest_IntArray()
        {
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            Guid testGuid = Guid.NewGuid();
            int[] testIntArray = new int[] { 1, 5, 8, 11 };
            string query = "?guid_param=" + testGuid.ToString() + "&bool_param=true&int_array_param=1,5,8,11";

            TestQueryParameters actual = target.LoadParameters<TestQueryParameters>(query);

            Assert.IsNotNull(actual);
            Assert.IsNotNull(actual.IntArrayParamNullable);
            CollectionAssert.AreEqual(testIntArray, actual.IntArrayParamNullable);
        }
        
        #endregion

        #region BuildQuery
        [TestMethod()]
        public void BuildQueryTest()
        {
            TestQueryParameters queryParams = new TestQueryParameters();
            queryParams.BoolParamRequired = true;
            queryParams.DateTimeParam = new DateTime(2010, 6, 4);
            queryParams.DateTimeParam2 = new DateTime(2011, 1, 16, 8, 45, 0);
            queryParams.GuidParamRequired = new Guid("{C5C9925B-46C8-4B2A-B47D-B961368E4DEF}");
            queryParams.IntArrayParamNullable = new int[] { 4, 6, 11, 89 };
            queryParams.IntParamNullable = 6;
            queryParams.StringParam = "hahaha";

            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            string query = target.BuildQuery(queryParams);
            //string expected = "bool_param=true&datetime_param=04-06-2010&datetime_param2=16-01-2011 8:45&guid_param={C5C9925B-46C8-4B2A-B47D-B961368E4DEF}&int_param=6&int_array_param=4,6,11,89&string_param=hahaha";

            TestQueryParameters queryParams2 = target.LoadParameters<TestQueryParameters>(query);
            
            Assert.IsNotNull(queryParams2);
            Assert.AreEqual(queryParams.BoolParamRequired, queryParams2.BoolParamRequired);
            Assert.AreEqual(queryParams.DateTimeParam, queryParams2.DateTimeParam);
            Assert.AreEqual(queryParams.DateTimeParam2, queryParams2.DateTimeParam2);
            Assert.AreEqual(queryParams.GuidParamRequired, queryParams2.GuidParamRequired);
            CollectionAssert.AreEqual(queryParams.IntArrayParamNullable, queryParams2.IntArrayParamNullable);
            Assert.AreEqual(queryParams.IntParamNullable, queryParams2.IntParamNullable);
            Assert.AreEqual(queryParams.StringParam, queryParams2.StringParam);
        }
        #endregion

        [TestMethod()]
        public void BuildNewUriTest()
        {
            TestQueryParameters queryParams = new TestQueryParameters();
            queryParams.BoolParamRequired = true;
            queryParams.DateTimeParam = new DateTime(2010, 6, 4);
            queryParams.DateTimeParam2 = new DateTime(2011, 1, 16, 8, 45, 0);
            queryParams.GuidParamRequired = new Guid("{C5C9925B-46C8-4B2A-B47D-B961368E4DEF}");
            queryParams.IntArrayParamNullable = new int[] { 4, 6, 11, 89 };
            queryParams.IntParamNullable = 6;
            queryParams.StringParam = "http://www.seznam.cz/inzerce/?v=15";

            Uri uri = new Uri("http://www.boldbrick.com/services?platform=xx&base=1");
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            Uri newUri = target.BuildNewUri(uri, queryParams);
            //string expected = "bool_param=true&datetime_param=04-06-2010&datetime_param2=16-01-2011 8:45&guid_param={C5C9925B-46C8-4B2A-B47D-B961368E4DEF}&int_param=6&int_array_param=4,6,11,89&string_param=hahaha";

            TestQueryParameters queryParams2 = target.LoadParameters<TestQueryParameters>(newUri.Query);

            Assert.IsNotNull(queryParams2);
            Assert.AreEqual(queryParams.BoolParamRequired, queryParams2.BoolParamRequired);
            Assert.AreEqual(queryParams.DateTimeParam, queryParams2.DateTimeParam);
            Assert.AreEqual(queryParams.DateTimeParam2, queryParams2.DateTimeParam2);
            Assert.AreEqual(queryParams.GuidParamRequired, queryParams2.GuidParamRequired);
            CollectionAssert.AreEqual(queryParams.IntArrayParamNullable, queryParams2.IntArrayParamNullable);
            Assert.AreEqual(queryParams.IntParamNullable, queryParams2.IntParamNullable);
            Assert.AreEqual(queryParams.StringParam, queryParams2.StringParam);
        }

        [TestMethod()]
        public void BuildNewUriTest2()
        {
            TestQueryParameters queryParams = new TestQueryParameters();
            queryParams.BoolParamRequired = true;
            queryParams.DateTimeParam = new DateTime(2010, 6, 4);
            queryParams.DateTimeParam2 = new DateTime(2011, 1, 16, 8, 45, 0);
            queryParams.GuidParamRequired = new Guid("{C5C9925B-46C8-4B2A-B47D-B961368E4DEF}");
            queryParams.IntArrayParamNullable = new int[] { 4, 6, 11, 89 };
            queryParams.IntParamNullable = 6;
            queryParams.StringParam = "http://www.seznam.cz/inzerce/?v=15&av=4";

            Uri uri = new Uri("http://www.boldbrick.com/services?platform=xx&base=1");
            RequestQueryParametersProvider target = new RequestQueryParametersProvider();
            Uri newUri = target.BuildNewUri(uri, queryParams);
            //string expected = "bool_param=true&datetime_param=04-06-2010&datetime_param2=16-01-2011 8:45&guid_param={C5C9925B-46C8-4B2A-B47D-B961368E4DEF}&int_param=6&int_array_param=4,6,11,89&string_param=hahaha";

            TestQueryParameters queryParams2 = target.LoadParameters<TestQueryParameters>(newUri.Query);

            Assert.IsNotNull(queryParams2);
            Assert.AreEqual(queryParams.BoolParamRequired, queryParams2.BoolParamRequired);
            Assert.AreEqual(queryParams.DateTimeParam, queryParams2.DateTimeParam);
            Assert.AreEqual(queryParams.DateTimeParam2, queryParams2.DateTimeParam2);
            Assert.AreEqual(queryParams.GuidParamRequired, queryParams2.GuidParamRequired);
            CollectionAssert.AreEqual(queryParams.IntArrayParamNullable, queryParams2.IntArrayParamNullable);
            Assert.AreEqual(queryParams.IntParamNullable, queryParams2.IntParamNullable);
            Assert.AreEqual(queryParams.StringParam, queryParams2.StringParam);
        }
    }
}
